home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Examples / ScrollDir / DirWindow.m < prev    next >
Encoding:
Text File  |  1996-02-08  |  25.8 KB  |  977 lines

  1. //=============================================================================
  2. //
  3. //        Copyright (C) 1995 by Paul S. McCarthy and Eric Sunshine.
  4. //                Written by Paul S. McCarthy and Eric Sunshine.
  5. //                            All Rights Reserved.
  6. //
  7. //        This notice may not be removed from this source code.
  8. //
  9. //        This object is included in the MiscKit by permission from the authors
  10. //        and its use is governed by the MiscKit license, found in the file
  11. //        "License.rtf" in the MiscKit distribution.    Please refer to that file
  12. //        for a list of all applicable permissions and restrictions.
  13. //
  14. //=============================================================================
  15. //-----------------------------------------------------------------------------
  16. // DirWindow.m
  17. //
  18. //        Manages window which displays directory listing.
  19. //
  20. //-----------------------------------------------------------------------------
  21. //-----------------------------------------------------------------------------
  22. // $Id$
  23. // $Log$
  24. //-----------------------------------------------------------------------------
  25. #import "DirWindow.h"
  26. #import "NameCache.h"
  27. #import "Defaults.h"
  28. #import <misckit/MiscTableScroll.h>
  29. #import <misckit/MiscTableCell.h>
  30. #import <assert.h>
  31. #import <errno.h>
  32. #import <appkit/NXImage.h>
  33. #import <appkit/workspaceRequest.h>
  34. #import <sys/dir.h>
  35.  
  36. #ifdef _POSIX_SOURCE
  37. # define GET_CURR_DIR(_BF_,_SZ_)        getcwd(_BF_,_SZ_)
  38. #else
  39. # define GET_CURR_DIR(_BF_,_SZ_)        getwd(_BF_)
  40. #endif
  41.  
  42. #define USE_PRIVATE_ZONE        1
  43.  
  44. enum
  45.     {
  46.     ICON_SLOT,
  47.     NAME_SLOT,
  48.     SIZE_SLOT,
  49.     MODIFIED_SLOT,
  50.     PERMS_SLOT,
  51.     OWNER_SLOT,
  52.     GROUP_SLOT,
  53.     HARDLINKS_SLOT,
  54.     SOFTLINK_SLOT,
  55.     MESSAGE_SLOT
  56.     };
  57. #define MAX_SLOT (MESSAGE_SLOT + 1)
  58.  
  59. #define CASCADE_MAX 10
  60. static int cascadeCounter = 0;
  61. static NXCoord cascadeOriginX;
  62. static NXCoord cascadeOriginY;
  63. static NXCoord cascadeDeltaX;
  64. static NXCoord cascadeDeltaY;
  65.  
  66. static BOOL defaultAutoSort;
  67. static BOOL defaultShowHidden;
  68. static BOOL defaultHighlightDirs;
  69. static NXColor defaultColor;
  70. static NXSize defaultWinSize;
  71. static Font* defaultFont;
  72. static List* openDirs = 0;
  73. static OwnerCache* owners = 0;
  74. static GroupCache* groups = 0;
  75.  
  76. static char const COLOR_DEF[]            = "DirColor";
  77. static char const SIZE_DEF[]            = "DirSize";
  78. static char const FONT_DEF[]            = "DirFont";
  79. static char const SORT_DEF[]            = "AutoSort";
  80. static char const HIDDEN_DEF[]            = "ShowHidden";
  81. static char const HLIGHT_DEF[]            = "HighlightDirs";
  82. static char const COL_SIZES_DEF[]        = "ColSizes";
  83. static char const COL_ORDER_DEF[]        = "ColOrder";
  84.  
  85.  
  86. //-----------------------------------------------------------------------------
  87. // normalize_path
  88. //-----------------------------------------------------------------------------
  89. static void normalize_path( char *buff, size_t sz )
  90.     {
  91.     char save_dir[ FILENAME_MAX + 1 ];
  92.     char tmp[ FILENAME_MAX + 1 ];
  93.  
  94.     if (buff != 0 && sz > 0)
  95.         {
  96.         if (GET_CURR_DIR( save_dir, sizeof(save_dir) ) != 0)
  97.             {
  98.             if (chdir( buff ) == 0)
  99.                 {
  100.                 if (GET_CURR_DIR( tmp, sizeof(tmp) ) != 0)
  101.                     {
  102.                     int const tmp_len = strlen( tmp );
  103.                     if (tmp_len < sz)
  104.                         strcpy( buff, tmp );
  105.                     else
  106.                         {
  107.                         strncpy( buff, tmp, sz );
  108.                         buff[ sz - 1 ] = '\0';
  109.                         }
  110.                     }
  111.                 chdir( save_dir );
  112.                 }
  113.             }
  114.         }
  115.     }
  116.  
  117.  
  118. //-----------------------------------------------------------------------------
  119. // fsize
  120. //-----------------------------------------------------------------------------
  121. static void fsize( size_t n, id cell )
  122.     {
  123.     [[cell setAlignment: NX_RIGHTALIGNED] setIntValue: n];
  124.     }
  125.  
  126.  
  127. //-----------------------------------------------------------------------------
  128. // mdate
  129. //-----------------------------------------------------------------------------
  130. static void mdate( time_t t, id cell )
  131.     {
  132.     #define BUFF_SIZE 64
  133.     char buff[ BUFF_SIZE ];
  134.     strftime( buff, BUFF_SIZE, "%m/%d/%y %H:%M", localtime(&t) );
  135.     [cell setStringValue:buff];
  136.     [cell setTag: (int) t ];
  137.     }
  138.  
  139.  
  140. //-----------------------------------------------------------------------------
  141. // perms
  142. //-----------------------------------------------------------------------------
  143. static void perms( unsigned int mode, id cell )
  144.     {
  145.     char buff[ 16 ];
  146.     char* s;
  147.     int ftype;
  148.     int c;
  149.  
  150.     s = buff;
  151.  
  152.     ftype = (mode & S_IFMT);
  153.     if (ftype == S_IFDIR)        c = 'd';
  154.     else if (ftype == S_IFCHR)    c = 'c';
  155.     else if (ftype == S_IFBLK)    c = 'b';
  156.     else if (ftype == S_IFREG)    c = '-';
  157.     else if (ftype == S_IFLNK)    c = 'l';
  158.     else if (ftype == S_IFSOCK) c = 's';
  159.     else c = '-';
  160.     *s++ = c;
  161.     *s++ = (mode & 0400) ? 'r' : '-';
  162.     *s++ = (mode & 0200) ? 'w' : '-';
  163.     *s++ = (mode & S_ISUID) ? 's' : (mode & 0100) ? 'x' : '-';
  164.     *s++ = (mode & 0040) ? 'r' : '-';
  165.     *s++ = (mode & 0020) ? 'w' : '-';
  166.     *s++ = (mode & S_ISGID) ? 's' : (mode & 0010) ? 'x' : '-';
  167.     *s++ = (mode & 0004) ? 'r' : '-';
  168.     *s++ = (mode & 0002) ? 'w' : '-';
  169.     *s++ = (mode & S_ISVTX) ? 't' : (mode & 0001) ? 'x' : '-';
  170.     *s = '\0';
  171.  
  172.     [cell setStringValue: buff];
  173.     [cell setTag: mode];
  174.     }
  175.  
  176.  
  177. //-----------------------------------------------------------------------------
  178. // owner
  179. //-----------------------------------------------------------------------------
  180. static void owner( unsigned int uid, id cell )
  181.     {
  182.     [cell setStringValueNoCopy: [owners lookup:uid] ];
  183.     }
  184.  
  185.  
  186. //-----------------------------------------------------------------------------
  187. // group
  188. //-----------------------------------------------------------------------------
  189. static void group( unsigned int gid, id cell )
  190.     {
  191.     [cell setStringValueNoCopy: [groups lookup:gid] ];
  192.     }
  193.  
  194.  
  195. //-----------------------------------------------------------------------------
  196. // image
  197. //-----------------------------------------------------------------------------
  198. static void image( char const* name, id cell, NXCoord w, NXCoord h )
  199.     {
  200.     NXCoord s = (w < h ? w : h) - 1.0;
  201.     NXSize sz = { s, s };
  202.     NXImage* i = [[Application workspace] getIconForFile: name];
  203.     [i setScalable: YES];
  204.     [i setSize: &sz];
  205.     [cell setImage: i];
  206.     }
  207.  
  208.  
  209.  
  210. //=============================================================================
  211. // IMPLEMENTATION
  212. //=============================================================================
  213. @implementation DirWindow
  214.  
  215. //-----------------------------------------------------------------------------
  216. // + initCascader
  217. //-----------------------------------------------------------------------------
  218. + (void) initCascader
  219.     {
  220.     NXSize screenSize;
  221.     [NXApp getScreenSize: &screenSize];
  222.     cascadeOriginX = screenSize.width / 4;
  223.     cascadeOriginY = screenSize.height - 20;
  224.     cascadeDeltaX = 20;
  225.     cascadeDeltaY = 20;
  226.     }
  227.  
  228.  
  229. //-----------------------------------------------------------------------------
  230. // + initialize
  231. //-----------------------------------------------------------------------------
  232. + initialize
  233.     {
  234.     if (self == [DirWindow class])
  235.         {
  236.         [self initCascader];
  237.         openDirs = [[List alloc] init];
  238.         owners = [OwnerCache commonInstance];
  239.         groups = [GroupCache commonInstance];
  240.         defaultColor = [Defaults getColor:COLOR_DEF fallback:NX_COLORLTGRAY];
  241.         defaultAutoSort = [Defaults getBool:SORT_DEF fallback:NO];
  242.         defaultShowHidden = [Defaults getBool:HIDDEN_DEF fallback:NO];
  243.         defaultHighlightDirs = [Defaults getBool:HLIGHT_DEF fallback:NO];
  244.         }
  245.     return self;
  246.     }
  247.  
  248.  
  249. //-----------------------------------------------------------------------------
  250. // - cascade
  251. //-----------------------------------------------------------------------------
  252. - (void) cascade
  253.     {
  254.     NXCoord top,left;
  255.     left = cascadeOriginX + (cascadeDeltaX * cascadeCounter);
  256.     top     = cascadeOriginY - (cascadeDeltaY * cascadeCounter);
  257.     [window moveTopLeftTo: left : top ];
  258.     if (++cascadeCounter >= CASCADE_MAX)
  259.         cascadeCounter = 0;
  260.     }
  261.  
  262.  
  263. //-----------------------------------------------------------------------------
  264. // - isDir:
  265. //-----------------------------------------------------------------------------
  266. - (BOOL) isDir:(int)r
  267.     {
  268.     unsigned int const m = (unsigned int) [[scroll cellAt:r:PERMS_SLOT] tag];
  269.     return ((m & S_IFMT) == S_IFDIR);
  270.     }
  271.  
  272.  
  273. //-----------------------------------------------------------------------------
  274. // - updateButtons
  275. //-----------------------------------------------------------------------------
  276. - (void) updateButtons
  277.     {
  278.     BOOL const enable = [scroll numSelectedRows] == 1 &&
  279.                         [self isDir:[scroll selectedRow]];
  280.     if (enable != [cdButton isEnabled])
  281.         [cdButton setEnabled: enable];
  282.     }
  283.  
  284.  
  285. //-----------------------------------------------------------------------------
  286. // - setRow:useOwner:color:
  287. //-----------------------------------------------------------------------------
  288. - (void) setRow:(int)r useOwner:(BOOL)useOwner color:(NXColor)color
  289.     {
  290.     int i;
  291.     for (i = MAX_SLOT; i-- >= 0; )
  292.         {
  293.         id cell = [scroll cellAt:r:i];
  294.         if (useOwner &&
  295.             [cell respondsTo:@selector(setUseOwnerBackgroundColor:)])
  296.             {
  297.             [cell setUseOwnerBackgroundColor:YES];
  298.             if ([cell respondsTo:@selector(setOwnerBackgroundColor:)])
  299.                 [cell setOwnerBackgroundColor:color];
  300.             }
  301.         else
  302.             {
  303.             if ([cell respondsTo: @selector(setBackgroundColor:)])
  304.                 [cell setBackgroundColor: color];
  305.             }
  306.         }
  307.     }
  308.  
  309.  
  310. //-----------------------------------------------------------------------------
  311. // - highlight:row:
  312. //-----------------------------------------------------------------------------
  313. - (void) highlight:(BOOL)flag row:(int)r
  314.     {
  315.     if (flag)
  316.         [self setRow:r useOwner:NO color:NX_COLORCYAN];
  317.     else
  318.         [self setRow:r useOwner:YES color:defaultColor];
  319.     }
  320.  
  321.  
  322. //-----------------------------------------------------------------------------
  323. // - highlightDirs:
  324. //-----------------------------------------------------------------------------
  325. - (void) highlightDirs:(BOOL)flag
  326.     {
  327.     int const N = [scroll numRows];
  328.     int i;
  329.     for (i = 0; i < N; i++)
  330.         if ([self isDir:i])
  331.             [self highlight:flag row:i];
  332.     }
  333.  
  334.  
  335. //-----------------------------------------------------------------------------
  336. // - freeImages
  337. //-----------------------------------------------------------------------------
  338. - (void) freeImages
  339.     {
  340.     int i;
  341.     int const n = [scroll numRows];
  342.     for (i = 0; i < n; i++)        
  343.         {
  344.         id cell = [scroll cellAt:i:ICON_SLOT];
  345.         id img    = [cell image];
  346.         [cell setImage:0];
  347.         [img free];
  348.         }
  349.     }
  350.  
  351.  
  352. //-----------------------------------------------------------------------------
  353. // - tableScroll:fontChangedFrom:to:
  354. //-----------------------------------------------------------------------------
  355. - tableScroll:(MiscTableScroll*)ts
  356.         fontChangedFrom:(Font*)oldFont
  357.         to:(Font*)newFont
  358.     {
  359.     defaultFont = newFont;
  360.     [Defaults set:FONT_DEF font:defaultFont];
  361.     return self;
  362.     }
  363.  
  364.  
  365. //-----------------------------------------------------------------------------
  366. // - tableScroll:border:slotResized:
  367. //-----------------------------------------------------------------------------
  368. - tableScroll:(MiscTableScroll*)ts
  369.         border:(MiscBorderType)b
  370.         slotResized:(int)n
  371.     {
  372.     char* s;
  373.     assert( b == MISC_COL_BORDER );
  374.     s = [ts colSizesAsString:0 size:0 canExpand:YES];
  375.     [Defaults set:COL_SIZES_DEF str:s];
  376.     free( s );
  377.     return self;
  378.     }
  379.  
  380.  
  381. //-----------------------------------------------------------------------------
  382. // - tableScroll:border:slotDraggedFrom:to:
  383. //-----------------------------------------------------------------------------
  384. - tableScroll:(MiscTableScroll*)ts
  385.         border:(MiscBorderType)b
  386.         slotDraggedFrom:(int)fromPos
  387.         to:(int)toPos;
  388.     {
  389.     char* s;
  390.     assert( b == MISC_COL_BORDER );
  391.     s = [ts colOrderAsString:0 size:0 canExpand:YES];
  392.     [Defaults set:COL_ORDER_DEF str:s];
  393.     free( s );
  394.     return self;
  395.     }
  396.  
  397.  
  398. //-----------------------------------------------------------------------------
  399. // - fillScroll
  400. //-----------------------------------------------------------------------------
  401. - (void) fillScroll
  402.     {
  403.     size_t total_bytes = 0;
  404.     int dirlen;
  405.     char namebuff[ FILENAME_MAX + 1 ];
  406.     DIR* dirp;
  407.  
  408.     dirlen = strlen( path );
  409.     memcpy( namebuff, path, dirlen );
  410.  
  411.     if (dirlen == 0 || namebuff[ dirlen - 1 ] != '/')
  412.         namebuff[ dirlen++ ] = '/';
  413.  
  414.     [window disableDisplay];
  415.  
  416.     [self freeImages];
  417.     [scroll empty];
  418.  
  419.     if ((dirp = opendir( path )) == 0)
  420.         {
  421.         NXRunAlertPanel( "Can't Open",
  422.                 "Cannot open directory, %s\n%d:%s", "OK",0,0,
  423.                 path, errno, strerror(errno) );
  424.         }
  425.     else
  426.         {
  427.         int rc;
  428.         int row = -1;
  429.         struct stat st;
  430.         struct direct const* dp;
  431.  
  432.         while ((dp = readdir(dirp)) != 0)
  433.             {            // Do not include the "." (self) entry.
  434.             int const dlen = dp->d_namlen;
  435.             char const* const dname = dp->d_name;
  436.             BOOL const dot_name = (dname[0] == '.');
  437.             if ((dlen > 1 || !dot_name) &&        // exclude "."
  438.                 (showHidden || !dot_name ||
  439.                     (dlen == 2 && dname[1] == '.')))
  440.                 {
  441.                 [scroll addRow]; row++;
  442.                 [[scroll cellAt:row:NAME_SLOT] setStringValue:dname];
  443.                 strcpy( namebuff + dirlen, dname );
  444.                 if ((rc = lstat( namebuff, &st )) == 0)
  445.                     {
  446.                     if ((st.st_mode & S_IFMT) == S_IFLNK)        // soft-link?
  447.                         {
  448.                         char symbuf[ FILENAME_MAX + 1 ];
  449.                         int cc;
  450.                         cc = readlink( namebuff, symbuf, FILENAME_MAX );
  451.                         if (cc >= 0)
  452.                             {
  453.                             symbuf[ cc ] = '\0';
  454.                             [[scroll cellAt:row:SOFTLINK_SLOT]
  455.                                                 setStringValue:symbuf];
  456.                             rc = stat( namebuff, &st );
  457.                             }
  458.                         else
  459.                             rc = -1;
  460.                         }
  461.                     }
  462.                 if (rc == 0)
  463.                     {
  464.                     total_bytes += st.st_size;
  465.                     image( namebuff, [scroll cellAt:row:ICON_SLOT],
  466.                                 [scroll colSize:ICON_SLOT],
  467.                                 [scroll uniformSizeRows] );
  468.                     fsize( st.st_size, [scroll cellAt:row:SIZE_SLOT] );
  469.                     mdate( st.st_mtime,[scroll cellAt:row:MODIFIED_SLOT] );
  470.                     perms( st.st_mode, [scroll cellAt:row:PERMS_SLOT] );
  471.                     owner( st.st_uid, [scroll cellAt:row:OWNER_SLOT] );
  472.                     group( st.st_gid, [scroll cellAt:row:GROUP_SLOT] );
  473.                     [[scroll cellAt:row:HARDLINKS_SLOT]
  474.                                 setIntValue:st.st_nlink];
  475.                     [[scroll cellAt:row:MESSAGE_SLOT]
  476.                                 setStringValueNoCopy:""];
  477.                     if (highlightDirs && (st.st_mode & S_IFMT) == S_IFDIR)
  478.                         [self highlight:YES row:row];
  479.                     }
  480.                 else // (rc != 0)
  481.                     {
  482.                     int slot;
  483.                     [[scroll cellAt:row:MESSAGE_SLOT]
  484.                                 setStringValue: strerror(errno)];
  485.                     for (slot = SIZE_SLOT; slot < SOFTLINK_SLOT; slot++)
  486.                         [[scroll cellAt:row:slot] setStringValueNoCopy:"?"];
  487.                     }
  488.                 }
  489.             }
  490.         closedir(dirp);
  491.         }
  492.     if ([scroll autoSortRows])
  493.         [scroll sortRows];
  494.     [scroll sizeToCells];
  495.     sprintf( namebuff, "%d files   %lu bytes", [scroll numRows], total_bytes );
  496.     [countField setStringValue:namebuff];
  497.     [self updateButtons];
  498.     [[window reenableDisplay] display];
  499.     }
  500.  
  501.  
  502. //-----------------------------------------------------------------------------
  503. // - setPath:
  504. //-----------------------------------------------------------------------------
  505. - (void) setPath:(char const*)dirname
  506.     {
  507.     NXZone* const z = [self zone];
  508.     int dirlen;
  509.     if (path != 0) NXZoneFree( z, path );
  510.     if (dirname == 0) dirname = NXHomeDirectory();
  511.     if (dirname == 0) dirname = "/";
  512.     dirlen = strlen( dirname ) + 1;
  513.     path = (char*) NXZoneMalloc( z, dirlen );
  514.     memcpy( path, dirname, dirlen );
  515.     [window setTitle: path];
  516.     }
  517.  
  518.  
  519. //-----------------------------------------------------------------------------
  520. // - load:
  521. //-----------------------------------------------------------------------------
  522. - (void) load:(char const*)dirname
  523.     {
  524.     [self setPath:dirname];
  525.     [self fillScroll];
  526.     }
  527.  
  528.  
  529. //-----------------------------------------------------------------------------
  530. // - open:
  531. //-----------------------------------------------------------------------------
  532. - open:sender
  533.     {
  534.     if ([scroll hasRowSelection])
  535.         {
  536.         int path_len;
  537.         char buff[ FILENAME_MAX + 1 ];
  538.         int i;
  539.         MiscIntList* list = [[MiscIntList allocFromZone:[self zone]] init];
  540.  
  541.         strcpy( buff, path );
  542.         path_len = strlen( buff );
  543.         if (path_len == 0 || buff[path_len - 1] != '/')
  544.             {
  545.             buff[ path_len++ ] = '/';
  546.             buff[ path_len ] = '\0';
  547.             }
  548.             
  549.         [scroll selectedRows: list];
  550.         for (i = [list count]; i-- > 0; )
  551.             {
  552.             unsigned int mode;
  553.             int row = [list intAt:i];
  554.  
  555.             strcpy( buff + path_len,
  556.                         [[scroll cellAt:row:NAME_SLOT] stringValue] );
  557.  
  558.             mode = (unsigned int)[[scroll cellAt:row:PERMS_SLOT] tag];
  559.             if ((mode & S_IFMT) == S_IFDIR)
  560.                 [[self class] launchDir: buff];
  561.             else
  562.                 [[Application workspace] openFile: buff];
  563.             }
  564.         [list free];
  565.         }
  566.     return self;
  567.     }
  568.  
  569.  
  570. //-----------------------------------------------------------------------------
  571. // - destroy:
  572. //-----------------------------------------------------------------------------
  573. - destroy:sender
  574.     {
  575.     if ([scroll hasRowSelection])
  576.         {
  577.         size_t total_len = 0;
  578.         char* file_list;
  579.         int i;
  580.         NXZone* const z = [self zone];
  581.         MiscIntList* list = [[MiscIntList allocFromZone:z] init];
  582.  
  583.         [scroll selectedRows: list];
  584.  
  585.         for (i = [list count]; i-- > 0; )
  586.             {
  587.             int const row = [list intAt:i];
  588.             char const* const s = [[scroll cellAt:row:NAME_SLOT] stringValue];
  589.             if (s != 0)
  590.                 total_len += strlen( s ) + 1;
  591.             }
  592.  
  593.         file_list = (char*) NXZoneMalloc( z, total_len + 1 );
  594.         
  595.         total_len = 0;
  596.         for (i = [list count]; i-- > 0; )
  597.             {
  598.             int row = [list intAt:i];
  599.             char const* const s = [[scroll cellAt:row:NAME_SLOT] stringValue];
  600.             if (s != 0)
  601.                 {
  602.                 int const len = strlen( s );
  603.                 strcpy( file_list + total_len, s );
  604.                 total_len += len;
  605.                 file_list[ total_len++ ] = '\t';
  606.                 }
  607.             }
  608.         file_list[ total_len ] = '\0';
  609.  
  610.         [[Application workspace]
  611.                 performFileOperation: WSM_DESTROY_OPERATION
  612.                         source: path
  613.                         destination: ""
  614.                         files: file_list
  615.                         options: ""];
  616.  
  617.         NXZoneFree( z, file_list );
  618.         [list free];
  619.         [self fillScroll];
  620.         }
  621.     return self;
  622.     }
  623.  
  624.  
  625. //-----------------------------------------------------------------------------
  626. // - updatePressed:
  627. //-----------------------------------------------------------------------------
  628. - updatePressed:sender
  629.     {
  630.     [self fillScroll];
  631.     return self;
  632.     }
  633.  
  634.  
  635. //-----------------------------------------------------------------------------
  636. // - cdPressed:
  637. //-----------------------------------------------------------------------------
  638. - cdPressed:sender
  639.     {
  640.     if ([scroll numSelectedRows] == 1)
  641.         {
  642.         MiscCoord_P const row = [scroll selectedRow];
  643.         if ([self isDir:row])
  644.             {
  645.             char buff[ FILENAME_MAX * 2 + 1 ];
  646.             strcat( strcat( strcpy( buff, path ), "/" ),
  647.                 [[scroll cellAt:row:NAME_SLOT] stringValue] );
  648.             normalize_path( buff, sizeof(buff) );
  649.             [self load:buff];
  650.             }
  651.         }
  652.     return self;
  653.     }
  654.  
  655.  
  656. //-----------------------------------------------------------------------------
  657. // - autoSortClick:
  658. //-----------------------------------------------------------------------------
  659. - autoSortClick:sender
  660.     {
  661.     BOOL const switchState = [autoSortSwitch state];
  662.     if (autoSort != switchState)
  663.         {
  664.         defaultAutoSort = autoSort = switchState;
  665.         [Defaults set:SORT_DEF bool:defaultAutoSort];
  666.         [scroll setAutoSortRows:switchState];
  667.         if (switchState)
  668.             [scroll sortRows];
  669.         }
  670.     return self;
  671.     }
  672.  
  673.  
  674. //-----------------------------------------------------------------------------
  675. // - hiddenFilesClick:
  676. //-----------------------------------------------------------------------------
  677. - hiddenFilesClick:sender
  678.     {
  679.     BOOL const switchState = [hiddenFilesSwitch state];
  680.     if (showHidden != switchState)
  681.         {
  682.         defaultShowHidden = showHidden = switchState;
  683.         [Defaults set:HIDDEN_DEF bool:defaultShowHidden];
  684.         [self fillScroll];
  685.         }
  686.     return self;
  687.     }
  688.  
  689.  
  690. //-----------------------------------------------------------------------------
  691. // - highlightClick:
  692. //-----------------------------------------------------------------------------
  693. - highlightClick:sender
  694.     {
  695.     BOOL const switchState = [highlightSwitch state];
  696.     if (highlightDirs != switchState)
  697.         {
  698.         defaultHighlightDirs = highlightDirs = switchState;
  699.         [Defaults set:HLIGHT_DEF bool:defaultHighlightDirs];
  700.         [self highlightDirs:highlightDirs];
  701.         [scroll display];
  702.         }
  703.     return self;
  704.     }
  705.  
  706.  
  707. //-----------------------------------------------------------------------------
  708. // - didClick:
  709. //-----------------------------------------------------------------------------
  710. - didClick:sender
  711.     {
  712.     [self updateButtons];
  713.     return self;
  714.     }
  715.  
  716.  
  717. //-----------------------------------------------------------------------------
  718. // - didDoubleClick:
  719. //-----------------------------------------------------------------------------
  720. - didDoubleClick:sender
  721.     {
  722.     [self open:sender];
  723.     return self;
  724.     }
  725.  
  726.  
  727. //-----------------------------------------------------------------------------
  728. // - free
  729. //-----------------------------------------------------------------------------
  730. - free
  731.     {
  732. #if(USE_PRIVATE_ZONE)
  733.     NXZone* const z = [self zone];
  734. #endif
  735.     [window close];
  736.     [window disableDisplay];
  737.     [self freeImages];
  738.     [window free];
  739.     if (path != 0)
  740.         free( path );
  741.     [super free];
  742. #if(USE_PRIVATE_ZONE)
  743.     NXDestroyZone( z );
  744. #endif
  745.     return 0;
  746.     }
  747.  
  748.  
  749. //-----------------------------------------------------------------------------
  750. // - makeKeyAndOrderFront:
  751. //-----------------------------------------------------------------------------
  752. - makeKeyAndOrderFront:sender
  753.     {
  754.     [window makeKeyAndOrderFront:sender];
  755.     return self;
  756.     }
  757.  
  758.  
  759. //-----------------------------------------------------------------------------
  760. // - windowWillClose:
  761. //-----------------------------------------------------------------------------
  762. - windowWillClose:sender
  763.     {
  764.     [openDirs removeObject:self];
  765.     [NXApp delayedFree: self];
  766.     return self;
  767.     }
  768.  
  769.  
  770. //-----------------------------------------------------------------------------
  771. // - windowDidResize:
  772. //-----------------------------------------------------------------------------
  773. - windowDidResize:sender
  774.     {
  775.     NXRect r; [sender getFrame:&r];
  776.     if (r.size.width  != defaultWinSize.width ||
  777.         r.size.height != defaultWinSize.height)
  778.         {
  779.         defaultWinSize = r.size;
  780.         [Defaults set:SIZE_DEF size:defaultWinSize];
  781.         }
  782.     return self;
  783.     }
  784.  
  785.  
  786. //-----------------------------------------------------------------------------
  787. // - setDefaultColor
  788. //-----------------------------------------------------------------------------
  789. - (void) setDefaultColor: (NXColor)c
  790.     {
  791.     defaultColor = c;
  792.     [Defaults set:COLOR_DEF color:c];
  793.     }
  794.  
  795.  
  796. //-----------------------------------------------------------------------------
  797. // - setDaColors:
  798. //-----------------------------------------------------------------------------
  799. - (void) setDaColors: (NXColor)c
  800.     {
  801.     [window disableDisplay];
  802.     [window setBackgroundColor:c];
  803.     [scroll setColor:c];
  804.     [window reenableDisplay];
  805.     }
  806.  
  807.  
  808. //-----------------------------------------------------------------------------
  809. // - draggingEntered:
  810. //-----------------------------------------------------------------------------
  811. - (NXDragOperation) draggingEntered:(id<NXDraggingInfo>)sender
  812.     {
  813.     return ([sender draggingSourceOperationMask] & NX_DragOperationGeneric ?
  814.                 NX_DragOperationGeneric : NX_DragOperationNone);
  815.     }
  816.  
  817.  
  818. //-----------------------------------------------------------------------------
  819. // - performDragOperation:
  820. //-----------------------------------------------------------------------------
  821. - (BOOL) performDragOperation:(id<NXDraggingInfo>)sender
  822.     {
  823.     [self setDefaultColor:
  824.                 NXReadColorFromPasteboard( [sender draggingPasteboard] )];
  825.     [self setDaColors: defaultColor];
  826.     [window display];
  827.     return YES;
  828.     }
  829.  
  830.  
  831. //-----------------------------------------------------------------------------
  832. // - initDefaults
  833. //-----------------------------------------------------------------------------
  834. - (void) initDefaults
  835.     {
  836.     static BOOL initialized = NO;
  837.     if (!initialized)
  838.         {
  839.         NXRect r; [window getFrame:&r];
  840.         defaultWinSize = r.size;
  841.  
  842.         defaultFont = [Defaults getFont:FONT_DEF fallback:[scroll font]];
  843.     
  844.         initialized = YES;
  845.         }
  846.     }
  847.  
  848.  
  849. //-----------------------------------------------------------------------------
  850. // - loadDefaults
  851. //-----------------------------------------------------------------------------
  852. - (void) loadDefaults
  853.     {
  854.     NXRect r;
  855.     char const* s;
  856.  
  857.     [window getFrame:&r];
  858.     r.size = [Defaults getSize:SIZE_DEF fallback:defaultWinSize];
  859.     [window placeWindow:&r];
  860.  
  861.     autoSort = defaultAutoSort;
  862.     showHidden = defaultShowHidden;
  863.     highlightDirs = defaultHighlightDirs;
  864.  
  865.     [autoSortSwitch setState:autoSort];
  866.     [hiddenFilesSwitch setState:showHidden];
  867.     [highlightSwitch setState:highlightDirs];
  868.  
  869.     [scroll setAutoSortRows:autoSort];
  870.     [scroll setFont:defaultFont];
  871.     [self setDaColors: defaultColor];
  872.  
  873.     s = [Defaults getStr:COL_SIZES_DEF fallback:0];
  874.     if (s)
  875.         [scroll setColSizesFromString:s];
  876.  
  877.     s = [Defaults getStr:COL_ORDER_DEF fallback:0];
  878.     if (s)
  879.         [scroll setColOrderFromString:s];
  880.     }
  881.  
  882.  
  883. //-----------------------------------------------------------------------------
  884. // - initDir:
  885. //-----------------------------------------------------------------------------
  886. - initDir:(char const*)dirname
  887.     {
  888.     char buff[ FILENAME_MAX + 1 ];
  889.     NXZone* const z = [self zone];
  890.  
  891.     [super init];
  892.     [[NXBundle bundleForClass:[self class]]
  893.         getPath:buff forResource:[[self class] name] ofType:"nib"];
  894.     [NXApp loadNibFile:buff owner:self withNames:NO fromZone:z];
  895.     [window registerForDraggedTypes:&NXColorPboardType count:1];
  896.     path = 0;
  897.     [scroll setDoubleAction: @selector(didDoubleClick:)];
  898.     [self initDefaults];
  899.     [self loadDefaults];
  900.     [self load:dirname];
  901.     [openDirs addObject:self];
  902.     [self cascade];
  903.     [window makeKeyAndOrderFront:self];
  904.     return self;
  905.     }
  906.  
  907.  
  908. //-----------------------------------------------------------------------------
  909. // - init
  910. //-----------------------------------------------------------------------------
  911. - init
  912.     {
  913.     return [self initDir: NXHomeDirectory()];
  914.     }
  915.  
  916.  
  917. //-----------------------------------------------------------------------------
  918. // - path
  919. //-----------------------------------------------------------------------------
  920. - (char const*) path
  921.     {
  922.     return path;
  923.     }
  924.  
  925.  
  926. //-----------------------------------------------------------------------------
  927. // + findDir:
  928. //-----------------------------------------------------------------------------
  929. + (DirWindow*) findDir:(char const*) normalized_path
  930.     {
  931.     DirWindow* p = 0;
  932.     char const* s;
  933.     unsigned int i;
  934.     unsigned int const lim = [openDirs count];
  935.     if (normalized_path != 0)
  936.         {
  937.         for (i = 0;     i < lim;  i++)
  938.             {
  939.             p = (DirWindow*) [openDirs objectAt:i];
  940.             s = [p path];
  941.             if (s != 0 && strcmp( s, normalized_path ) == 0)
  942.                 return p;
  943.             }
  944.         }
  945.     return 0;
  946.     }
  947.  
  948.  
  949. //-----------------------------------------------------------------------------
  950. // + launchDir:
  951. //-----------------------------------------------------------------------------
  952. + launchDir: (char const*) dirname
  953.     {
  954.     DirWindow* p = 0;
  955.     char buff[ FILENAME_MAX + 1 ];
  956.     if (dirname == 0) dirname = NXHomeDirectory();
  957.     if (dirname == 0) dirname = "/";
  958.     strncpy( buff, dirname, sizeof(buff) );
  959.     buff[ sizeof(buff) - 1 ] = '\0';
  960.     normalize_path( buff, sizeof(buff) );
  961.     if ((p = [self findDir:buff]) != 0)
  962.         [p makeKeyAndOrderFront:self];
  963.     else
  964.         {
  965. #if(USE_PRIVATE_ZONE)
  966.         NXZone* z = NXCreateZone( vm_page_size, vm_page_size, YES );
  967.         p = [[self allocFromZone:z] initDir:buff];
  968. #else
  969.         p = [[self alloc] initDir:buff];
  970. #endif
  971.         }
  972.     return p;
  973.     }
  974.  
  975.  
  976. @end
  977.